package de.breitbeil.jbooking.task;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.sql.Connection;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.sql.DataSource;

import org.apache.derby.impl.load.Export;
import org.springframework.richclient.application.Application;
import org.springframework.richclient.application.ApplicationDescriptor;

import de.breitbeil.jbooking.ui.form.ExportFormObject;

public class DerbyExportTask extends AbstractTask<Void, Void> {

    private DataSource dataSource;
    private ExportFormObject config;

    public DerbyExportTask(ExportFormObject config, DataSource dataSource) {
        super("derbyExportTask");
        
        this.config = config;
        this.dataSource = dataSource;
    }

    /**
     * Creates a zip archive with csv files for each database table
     * and a jbooking.txt file containing the version und build of JBooking. 
     */
    protected Void doInBackground() throws Exception {

        Connection con = dataSource.getConnection();
        String schemaName = "JBOOKING";
        String[] tableNames = new String[]{"PERSON", "EVENT", "BOOKING" , "T_BOOKING_TYPE"};
        String outputFileName = getOutputFileName(config);
        String columnDelimeter = ",";
        String characterDelimeter = "\"";
        String codeset = "ISO-8859-1";



        /*
         * SYSCS_EXPORT_TABLE  system Procedure from ij or from a Java application
         * invokes  this method to perform export of  a table data to a file.
         * @param con    The Derby database connection URL for the database containing the table
         * @param schemaName    schema name of the table data is being exported from
         * @param tableName     Name of the Table from which  data has to be exported.
         * @param outputFileName Name of the file to  which data has to be exported.
         * @param columnDelimeter  Delimiter that seperates columns in the output file
         * @param characterDelimeter  Delimiter that is used to quoate non-numeric types
         * @param codeset           Codeset that should be used to write  the data to  the file
         * @exception SQL Exception on errors
         */
        //Export.exportTable(con, schemaName, tableName, outputFileName, columnDelimeter, characterDelimeter, codeset);


        FileInputStream in;
        byte[] data = new byte[1024];
        int read = 0;

        ZipOutputStream out = new ZipOutputStream(new FileOutputStream(outputFileName));
        out.setMethod(ZipOutputStream.DEFLATED);

        // Write JBooking Version in Zip archive
        ApplicationDescriptor appDesc = Application.instance().getDescriptor();
        String versionString = "Version:"+appDesc.getVersion()+"\n";
        String buildString = "Build:"+appDesc.getBuildId()+"\n";
        
        ZipEntry entry = new ZipEntry("jbooking.txt");
        out.putNextEntry(entry);
        out.write(versionString.getBytes());
        out.write(buildString.getBytes());
        out.closeEntry();
        
        // Create for every table one csv file in zip archive
        for (int i = 0; i < tableNames.length; i++) {
            String tableName = tableNames[i];
            
            StringBuilder tempFile = new StringBuilder();
            tempFile.append(System.getProperty("java.io.tmpdir"));
            tempFile.append(System.getProperty("file.separator"));
            tempFile.append("JBooking" + tableName + new Object() + ".csv");
            
            Export.exportTable(con, schemaName, tableName, tempFile.toString(), columnDelimeter, characterDelimeter, codeset);
            
            // Eintrag fuer neue Datei anlegen
            entry = new ZipEntry(tableName+".csv");
            in = new FileInputStream(tempFile.toString());
            
            // Neuer Eintrag dem Archiv hinzufuegen
            out.putNextEntry(entry);
            
            // Hinzufuegen der Daten zum neuen Eintrag
            while((read = in.read(data, 0, 1024)) != -1)
                out.write(data, 0, read);
            
            out.closeEntry(); // Neuen Eintrag abschliessen
            in.close();
            new File(tempFile.toString()).delete();
        }
        
        out.close();

        return null;
    }


    private String getOutputFileName(ExportFormObject config) {
        String output = config.getOutput();

        if(!output.toLowerCase().endsWith(".zip")) {
            output = output + ".zip";
        }

        return output;
    }
}
